package com.hz.cheetah.common.sys;

/**
 * Created by yangchuan on 16/6/28.
 */


import java.lang.management.ManagementFactory;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.ThreadMXBean;
import java.util.Iterator;
import java.util.List;

public abstract class JvmRuntime {
    protected static final long SECOND = 1000L;
    protected static final long MINUTE = 60000L;
    protected static final long HOUR = 3600000L;
    private int cpus = Runtime.getRuntime().availableProcessors();
    private long prevUptime = 0L;
    private long prevCputime = 0L;
    private float cpuUsage = 0.0F;
    private MemoryPoolMXBean oldMemPool = null;

    public static JvmRuntime getRuntime() {
        return MonitorRuntime.getMonitorRuntime();
    }

    public abstract void addShutdownHook(ShutdownHook shutdownHook);

    protected JvmRuntime() {
        List memPools = ManagementFactory.getMemoryPoolMXBeans();
        Iterator iterator = memPools.iterator();

        while(iterator.hasNext()) {
            MemoryPoolMXBean memoryPoolMXBean = (MemoryPoolMXBean)iterator.next();
            if(memoryPoolMXBean.getName().toLowerCase().contains("old")) {
                this.oldMemPool = memoryPoolMXBean;
                break;
            }
        }

    }

    public ResourceState getMemoryState() {
        return ResourceState.GREEN;
    }

    public ResourceState getCPUState() {
        return ResourceState.GREEN;
    }

    public long getProcessCPUTime() {
        long result = 0L;
        OperatingSystemMXBean osMXBean = ManagementFactory.getOperatingSystemMXBean();
        if(osMXBean instanceof com.sun.management.OperatingSystemMXBean) {
            com.sun.management.OperatingSystemMXBean thBean = (com.sun.management.OperatingSystemMXBean)osMXBean;
            result = thBean.getProcessCpuTime();
        } else {
            ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
            long[] threadIds = threadMXBean.getAllThreadIds();
            int len$ = threadIds.length;

            for(int i = 0; i < len$; ++i) {
                long thid = threadIds[i];
                result += threadMXBean.getThreadCpuTime(thid);
            }
        }

        return result;
    }

    public long getPID() {
        String processName = ManagementFactory.getRuntimeMXBean().getName();
        return Long.parseLong(processName.split("@")[0]);
    }

    public long getUptime() {
        return ManagementFactory.getRuntimeMXBean().getUptime();
    }

    public String getUptimeString() {
        long uptime = ManagementFactory.getRuntimeMXBean().getUptime();
        long days = uptime / 86400000L;
        long hours = (uptime - days * 24L * 3600000L) / 3600000L;
        long minutes = (uptime - (days * 24L * 3600000L + hours * 3600000L)) / 60000L;
        long seconds = (uptime - (days * 24L * 3600000L + hours * 3600000L + minutes * 60000L)) / 1000L;
        StringBuilder sb = new StringBuilder();
        sb.append(days > 0L?days + (days == 1L?" day":" days"):"");
        if(hours > 0L) {
            if(sb.length() > 0) {
                sb.append(", ");
            }

            sb.append(hours + (hours == 1L?" hour":" hours"));
        }

        if(days == 0L && minutes > 0L) {
            if(sb.length() > 0) {
                sb.append(", ");
            }

            sb.append(minutes + (minutes == 1L?" min":" mins"));
        }

        if(days == 0L && hours == 0L && seconds > 0L) {
            if(sb.length() > 0) {
                sb.append(", ");
            }

            sb.append(seconds + " sec");
        }

        return sb.toString();
    }

    public int getCPUsNumber() {
        return this.cpus;
    }

    public float getCPUUsage() {
        long currCputime = -1L;
        long elapsedCpu = -1L;
        long currUptime = this.getUptime();
        long elapsedTime = currUptime - this.prevUptime;
        if(this.prevUptime > 0L && elapsedTime > 500L) {
            currCputime = this.getProcessCPUTime();
            elapsedCpu = currCputime - this.prevCputime;
            this.cpuUsage = Math.min(99.99F, (float)elapsedCpu / ((float)elapsedTime * 10000.0F * (float)this.cpus));
        }

        if(elapsedTime > 500L) {
            this.prevUptime = currUptime;
            this.prevCputime = currCputime;
        }

        return this.cpuUsage;
    }

    public double getLoadAverage() {
        return ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage();
    }

    public int getThreadsNumber() {
        return ManagementFactory.getThreadMXBean().getThreadCount();
    }

    public long getHeapMemMax() {
        if(this.oldMemPool != null) {
            MemoryUsage memUsage = this.oldMemPool.getUsage();
            return memUsage.getMax();
        } else {
            return ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getMax();
        }
    }

    public long getHeapMemUsed() {
        if(this.oldMemPool != null) {
            MemoryUsage memUsage = this.oldMemPool.getUsage();
            return memUsage.getUsed();
        } else {
            return ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed();
        }
    }

    public float getHeapMemUsage() {
        return (float)this.getHeapMemUsed() * 100.0F / (float)this.getHeapMemMax();
    }

    public long getNonHeapMemMax() {
        return ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getMax();
    }

    public long getNonHeapMemUsed() {
        return ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getUsed();
    }

    public float getNonHeapMemUsage() {
        return (float)this.getNonHeapMemUsed() * 100.0F / (float)this.getNonHeapMemMax();
    }
}

